'use strict';
let uniID = require('uni-id')
const createConfig = require('uni-config-center')
const uniIdConfig = createConfig({
    pluginId: 'uni-id'
}).config()
const db = uniCloud.database()
const dbCmd = db.command
const usersDB = db.collection('uni-id-users')
const deviceDB = db.collection('uni-id-device')
exports.main = async (event, context) => {
    console.log({
        context
    });
    //UNI_WYQ:这里的uniID换成新的，保证多人访问不会冲突
    uniID = uniID.createInstance({
        context
    })
    console.log('event : ' + JSON.stringify(event))
    /*
    1.event为客户端 uniCloud.callFunction填写的data的值，这里介绍一下其中的属性
        action：表示要执行的任务名称、比如：登录login、退出登录 logout等
        params：业务数据内容
        uniIdToken：系统自动传递的token，数据来源客户端的 uni.getStorageSync('uni_id_token')
    */
    const {
        action,
        uniIdToken,
        inviteCode
    } = event;
    const deviceInfo = event.deviceInfo || {};
    let params = event.params || {},
        tokenExpired, needCaptcha;
    /*
    2.在某些操作之前我们要对用户对身份进行校验（也就是要检查用户的token）再将得到的uid写入params.uid
        校验用到的方法是uniID.checkToken 详情：https://uniapp.dcloud.io/uniCloud/uni-id?id=checktoken
        讨论，我们假设一个这样的场景，代码如下。
        如：
        uniCloud.callFunction({
            name:"xxx",
            data:{
                "params":{
                    uid:"通过某种方式获取来的别人的uid"
                }
            }
        })
        用户就这样轻易地伪造了他人的uid传递给服务端，有一句话叫：前端传来的数据都是不可信任的
        所以这里我们需要将uniID.checkToken返回的uid写入到params.uid
    */
    let noCheckAction = ['register', 'checkToken', 'login', 'logout', 'sendSmsCode', 'getNeedCaptcha',
        'createCaptcha', 'verifyCaptcha', 'refreshCaptcha', 'inviteLogin', 'loginByWeixin',
        'loginByUniverify', 'loginByApple', 'loginBySms', 'resetPwdBySmsCode', 'registerAdmin'
    ]
    if (!noCheckAction.includes(action)) {
        if (!uniIdToken) {
            return {
                code: 403,
                msg: '缺少token'
            }
        }
        let payload = await uniID.checkToken(uniIdToken)
        if (payload.code && payload.code > 0) {
            return payload
        }
        params.uid = payload.uid
        tokenExpired = payload.tokenExpired
    }

    //禁止前台用户传递角色
    if (action.slice(0, 7) == "loginBy") {
        if (params.role) {
            return {
                code: 403,
                msg: '禁止前台用户传递角色'
            }
        }
    }

    // 3.注册成功后触发。
    async function registerSuccess(res) {
        //用户接受邀请
        if (inviteCode) {
            await uniID.acceptInvite({
                inviteCode,
                uid
            });
        }
        //添加当前用户设备信息
        await addDeviceInfo(res)
    }
    //4.记录成功登录的日志方法
    const uniIdLog = async (res = {}) => {
        const now = Date.now()
        const uniIdLogCollection = db.collection('uni-id-log')
        let logData = {
            deviceId: context.DEVICEID,
            ip: context.CLIENTIP,
            type: res.type,
            ua: context.CLIENTUA,
            create_date: now,
            action
        };

        if (res.code === 0) {
            logData.user_id = res.uid
            logData.state = 1
            if (res.userInfo && res.userInfo.password) {
                delete res.userInfo.password
            }
            if (res.type == 'register') {
                await registerSuccess(res)
            }
            if (res.type == 'login') {
                if (Object.keys(deviceInfo).length) {
                    console.log(context.DEVICEID);
                    //避免重复新增设备信息，先判断是否已存在
                    let getDeviceRes = await deviceDB.where({
                        "device_id": context.DEVICEID
                    }).get()
                    if (getDeviceRes.data.length == 0) {
                        await addDeviceInfo(res)
                    } else {
                        await deviceDB.where({
                            "device_id": context.DEVICEID,
                        }).update({
                            ...deviceInfo,
                            "tokenExpired": res.tokenExpired,
                            "user_id": res.uid,
                            "device_id": context.DEVICEID,
                            "ua": context.CLIENTUA,
                            "platform": context.PLATFORM,
                            "create_date": Date.now(),
                            "last_active_date": Date.now(),
                            "last_active_ip": context.CLIENTIP
                        })
                    }
                }
            }
        } else {
            logData.state = 0
        }
        return await uniIdLogCollection.add(logData)
    }

    async function addDeviceInfo({
        uid,
        tokenExpired
    }) {
        return await deviceDB.add({
            ...deviceInfo,
            tokenExpired,
            "user_id": uid,
            "device_id": context.DEVICEID,
            "ua": context.CLIENTUA,
            "platform": context.PLATFORM,
            "create_date": Date.now(),
            "last_active_date": Date.now(),
            "last_active_ip": context.CLIENTIP
        })
    }

    //5.防止恶意破解操作，连续操作失败一定次数后，需要用户提供验证码
    // const isNeedCaptcha = async () => {
    //     //当用户最近“2小时内(recordDate)”操作失败达到2次(recordSize)时。要求用户提交验证码
    //     const now = Date.now(),
    //         recordDate = 120 * 60 * 1000,
    //         recordSize = 2;
    //     const uniIdLogCollection = db.collection('uni-id-log')
    //     let recentRecord = await uniIdLogCollection.where({
    //             ip: context.CLIENTIP,
    //             create_date: dbCmd.gt(now - recordDate),
    //             action
    //         })
    //         .orderBy('create_date', 'desc')
    //         .limit(recordSize)
    //         .get();
    //     return recentRecord.data.filter(item => item.state === 0).length === recordSize;
    // }

    let res = {}
    switch (action) { //根据action的值执行对应操作
        //注意 云函数不能调用自身，避免死循环，所以要指定name
        case 'register':
            if (!params.inviteCode) {
                return {
                    code: 500,
                    msg: '邀请码不能为空'
                }
            }
            res = await uniID.register(params)
            break;
        case 'checkToken':
            res = await uniID.checkToken(uniIdToken)
            break;
        case 'login':
            res = await uniID.login(params)
            break;
        case 'logout':
            res = await uniID.logout(params)
            break;
        case 'sendSmsCode':
            res = await uniID.sendSmsCode(params)
            break;
        case 'getNeedCaptcha':
            res = await isNeedCaptcha()
            break;
        case 'createCaptcha':
            res = await uniID.createCaptcha(params)
            break;
        case 'verifyCaptcha':
            res = await uniID.verifyCaptcha(params)
            break;
        case 'refreshCaptcha':
            res = await uniID.refreshCaptcha(params)
            break;
        case 'inviteLogin':
            if (!params.code) {
                return {
                    code: 500,
                    msg: '邀请码不能为空'
                }
            }
            res = await uniID.inviteLogin(params)
            break;
        case 'loginByWeixin':
            res = await uniID.loginByWeixin(params)
            break;
        case 'loginByUniverify':
            res = await uniID.loginByUniverify(params)
            break;
        case 'loginByApple':
            res = await uniID.loginByApple(params)
            break;
        case 'loginBySms':
            res = await uniID.loginBySms(params)
            break;
        case 'resetPwdBySmsCode':
            res = await uniID.resetPwdBySmsCode(params)
            break;
        case 'registerAdmin':
            res = await uniID.registerAdmin(params)
            break;
        case 'bindMobileBySms':
            res = await uniID.bindMobileBySms(params)
            break;
        default:
            return {
                code: 500,
                msg: 'action不在可执行范围'
            }
    }
    //防止恶意破解操作，连续操作失败一定次数后，需要用户提供验证码
    // if (res.code && res.code == 'BIZ_CAPTCHA_REQUIRED') {
    //     res = {
    //         errCode: 'CAPTCHA_REQUIRED',
    //         errMsg: '操作失败达到2次，请提交验证码'
    //     }
    // }
    //记录用户的操作行为
    await uniIdLog(res)
    return res
};
